package MyGame;

import DEMOS.LayerOne;
import DEMOS.LayerTwo;
import edu.chalmers.AV_2DPlatformerFramework.Control.KBListener;
import edu.chalmers.AV_2DPlatformerFramework.Game;
import edu.chalmers.AV_2DPlatformerFramework.Model.GameMap;
import edu.chalmers.AV_2DPlatformerFramework.Model.GameModel;
import edu.chalmers.AV_2DPlatformerFramework.Model.GameObject;
import edu.chalmers.AV_2DPlatformerFramework.Model.GameWorld;
import edu.chalmers.AV_2DPlatformerFramework.Model.Hitbox;
import edu.chalmers.AV_2DPlatformerFramework.Model.ObjectMover;
import edu.chalmers.AV_2DPlatformerFramework.Utility.Pair;
import edu.chalmers.AV_2DPlatformerFramework.Utility.Vector2D;
import edu.chalmers.AV_2DPlatformerFramework.Utility.VectorUtility;
import edu.chalmers.AV_2DPlatformerFramework.View.Camera;
import edu.chalmers.Framework_EXAMPLES.EXAMPLE_Object_TheDude;
import java.awt.event.KeyEvent;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;

/**
 * @version 0.3
 * @author Andrea Buchholz
 * @revised Joakim Karlsson 20140522
 * @revised Andrea Buchholz 20140522
 * @revised Andrea Buchholz 20140524
 */
public class MyGameModel extends GameModel {
    
    LayerOne layer1 = new LayerOne();
    LayerTwo layer2 = new LayerTwo();
    
    private final KBListener kbListener;
    private final Vector2D playerAcceleration;
    private boolean onSurface = false;
    private final GameObject player;
    private final GameObject gobj2, gobj3, gobj4, gobj5, gobj6, gobj7, gobj8, gobj9, gobj10, gobj11;
    
    /**
     * 
     * @param g
     * @param c
     * @throws Hitbox.HitboxMalformedException
     */
    public MyGameModel(Game g, Camera c) throws Hitbox.HitboxMalformedException{
        super();
    
        kbListener = g.getKeyListener();
        
        GameObject gobj1 = new Object_Edmund();
        this.player = gobj1;
        this.gobj2 = new Object_Bench();
        this.gobj3 = new Object_Pill();
        this.gobj4 = new Object_Box();
        this.gobj7 = new Object_Box();
        this.gobj8 = new Object_Box();
        this.gobj9 = new Object_Box();
        this.gobj10 = new Object_Box();
        this.gobj5 = new Object_MathDude();
        this.gobj6 = new Object_CanisterShot(new Vector2D(-3, 0));
        this.gobj11 = new EXAMPLE_Object_TheDude();
        
        player.setLayer(layer1);
        gobj2.setLayer(layer2);   
        gobj11.setLayer(layer2);
        gobj11.setStrata(-1000000);
        
        gobj1.setVelocity(new Vector2D(0.5, 0.1));
        gobj2.setVelocity(new Vector2D(-0.7, -0.35));
        gobj5.setVelocity(new Vector2D(3, 0));
        
        gobj1.setPosition(new Vector2D(100, 800));
        gobj2.setPosition(new Vector2D(1200, 850));
        gobj3.setPosition(new Vector2D(900, 877));
        gobj4.setPosition(new Vector2D(500, 866));
        gobj5.setPosition(new Vector2D(2000, 700));
        gobj6.setPosition(new Vector2D(1700, 725));
        gobj7.setPosition(new Vector2D(545, 866));
        gobj8.setPosition(new Vector2D(590, 866));
        gobj9.setPosition(new Vector2D(545, 832));
        gobj10.setPosition(new Vector2D(590, 832));
        gobj11.setPosition(new Vector2D(1400, 700));
        
                
        GameObject[] uniqueObjects = {
                                        gobj1,
                                        gobj2,
                                        gobj3,
                                        gobj4,
                                        gobj5,
                                        gobj6,
                                        gobj7,
                                        gobj8,
                                        gobj9,
                                        gobj10,
                                        gobj11,
                                     };

        c.setChaseDistance(230, 410);
        //c.placeRelativeToObject(player, 100, 1200);
        this.maps = new ArrayList<>();     
        GameWorld gw = new GameWorld    (new int[][] {
                                            {-50, 400,    400,    450,    450,    2500},
                                            {0,   0,      50,     50,     0,      0}},
                                            new Vector2D(0, 900), ".\\src\\main\\java\\Textures\\dirtTile.jpg"
                                         );
        playerAcceleration = new Vector2D(0, 0);
        this.maps = new ArrayList<>();
        this.maps.add(new GameMap(uniqueObjects, gw)); 
        this.maps.get(0).setMainActor(player);
    }
    
     public void finishedLevel(){
        //TODO: om map är slut, kontrollera så att grandchildren >=3;
        //getPills() >=3
    }
    
    /**
     * //TODO Not fully functional yet!
     * Updates variable onSurface on whether or not player is on a surface.
//     */
//    public void onSurface(){
//        
//        GameObject[] objects = {gobj2, gobj3, gobj4, gobj5,gobj6,gobj7,gobj8,gobj9,gobj10};
//        
//        if (player.getPosition().getY() >= 800){
//            onSurface = true;
//        }
//        
//        else{
//            for(GameObject object: objects){
//            
//                int playerY = (int)player.getPosition().getY();
//                int playerX = (int)player.getPosition().getX();
//                int objectY = (int)object.getPosition().getY();
//                int objectX = (int)object.getPosition().getX();
//                Rectangle2D playerEdges = player.getHitbox().getBounds2D();
//                Rectangle2D objectEdges = object.getHitbox().getBounds2D();
//            
//                if((playerX <= objectX + objectEdges.getMaxX()) || 
//                    (playerX + playerEdges.getMaxX() >= objectX)){
//                    
//                    if( playerY+ playerEdges.getMaxY() >= objectY){
//                        onSurface = true;
//                    } 
//                }
//                else{
//                    onSurface = false;
//                }
//            }
//        }
//    }  
    public void characterMove(){
       
            ArrayList<KeyEvent> events = new ArrayList<>();
            Queue queue = kbListener.getQueue();
            
            if(queue.isEmpty()){
                return;
            }
            
            double newX = player.getVelocity().getX();
            double newY = player.getVelocity().getY() - 0.08;

            for(int j=0; j<queue.size(); j++){
                
                KeyEvent e = (KeyEvent) queue.poll();
                events.add(e);
          
                for(int i=0; i<events.size(); i++){
                    
                    int keyCode = events.get(i).getKeyCode();

                    if(keyCode == KeyEvent.VK_UP) {
                            newY = -4;
                            newX = 2;
                            //player.setVelocity(new Vector2D(player.getVelocity().getX(),-4));
                        //}
                    }
                    
                    if(keyCode == KeyEvent.VK_DOWN) {
                       newY = 4;
                        //}
                    }
        
                    if(keyCode == KeyEvent.VK_LEFT){
                        player.setCurrentTexture(1);
                            newX = -2;
                    }
        
                    if(keyCode == KeyEvent.VK_RIGHT){
                        
                        player.setCurrentTexture(0);
                        newX = 2;
                    }
                    
                    if(keyCode == KeyEvent.VK_SHIFT){
                        newX = 6;
                    }
                }
            }
//            if(player.getVelocity().getX() <0){
//                player.setCurrentTexture(currentMapIndex);
//            }
            player.setVelocity(new Vector2D(newX,newY));
//        }
//            
//        double px = player.getVelocity().getX() + newX;
//            
//        if(px>=2){
//            player.setVelocity(new Vector2D (2,newY));
//        }
//        else if (px<-2){
//            player.setVelocity(new Vector2D (-2,newY));
//        }
//        else{
//            player.setVelocity(new Vector2D (newX,newY));
//        }
    }
//        if(kbListener.getQueueSize() > 0){
//            Queue queue = kbListener.getQueue();
//            KeyEvent e = (KeyEvent) queue.poll();
//            int keyCode = e.getKeyCode();
//            
//            if((int) player.getPosition().getY() >= 499){
//                onSurface = true;
//            }
//                  
//            if(keyCode == KeyEvent.VK_DOWN){
//              //TODO crouch/nothing?
//            }
//        
//            if(keyCode == KeyEvent.VK_UP) {
//                if(onSurface){
////                    player.setVelocity(VectorUtility.add(player.getVelocity(),
////                        new Vector2D(player.getVelocity().getX(), -4)));
//                    player.setVelocity(new Vector2D(player.getVelocity().getX(),-4));
//                    onSurface = false;
//                }
//            }
//        
//            if(keyCode == KeyEvent.VK_LEFT){
//                //playerAcceleration = new Vector2D(-0.01, 0);
//              // player.setCurrentTexture(1);
//               if(onSurface){
//                   // Not finished
//                   // Accelerate when travelling in one direction.
////                   double acceleration = 0.2;
////                   KeyEvent next = (KeyEvent) queue.peek();
////                   int nextCode = next.getKeyCode();
////                   if(nextCode == KeyEvent.VK_LEFT){
////                       double vx = player.getVelocity().getX();
////                       vx -= acceleration;
////                       player.setVelocity(new Vector2D(vx, player.getVelocity().getY()));
////                    }
////                    else{
//                        player.setVelocity(new Vector2D(-1, 0));
//                    } 
//               else{
//                    player.setVelocity(new Vector2D(-1, player.getVelocity().getY()));
//               }  
//            }
//        
//            if(keyCode == KeyEvent.VK_RIGHT){
//                 //player.setCurrentTexture(0);
//                 double gravity = 0.08;
//                 
//                 if(onSurface){
//                    player.setVelocity(new Vector2D(1, -gravity));
//                 }
//                 else{  
//                    player.setVelocity(new Vector2D(1, player.getVelocity().getY()));
//               }
//            }
//        }
        //}
    
    //Denna behövs ej om vi ej använder acceleration.
    @Override
    public void moveActiveObjects() {
        ArrayList<GameObject> actors = maps.get(
                currentMapIndex).getObjects();
        Vector2D grav = maps.get(currentMapIndex).getGravity();
        Pair[] moves = new Pair[actors.size()];
        
        int i = 0;
        for(GameObject go : actors){
            if(go == player) {
                moves[i] = new Pair(
                        go, VectorUtility.add(grav, playerAcceleration));
                i++;
            } else {
                moves[i] = new Pair(go, grav);
                i++;
            }
        }
        ObjectMover.moveObjects(moves, actors);
        
    }
  
    @Override
    public synchronized void run() {   
        characterMove();
        moveActiveObjects();
    }
}